import { Input, NavBar } from 'antd-mobile'
import classnames from 'classnames'
import { useHistory } from 'react-router-dom'
import { Icon } from '@/components/Icon'
import styles from './index.module.scss'
import { useEffect, useRef, useState } from 'react'
import { io, Socket } from 'socket.io-client'
import { useSelector } from 'react-redux'
import { RootState } from '@/types/store'

// 聊天列表中包含了两种消息：
// 1 小智同学回复的消息 2 我们发送的消息。可以通过 type 来进行区分：
type ChatType = {
	type: 'xz' | 'user'
	message: string
}

const Chat = () => {
	const history = useHistory()
	const { token } = useSelector((state: RootState) => state.login)

	const [chatList, setChatList] = useState<ChatType[]>([])
	// 创建状态使用受控组件方式控制文本框的值
	const [value, setValue] = useState('')
	// 创建 ref 对象，来存储 socketio 实例，来实现多个方法中共享该变量
	// 保证在发送消息时可以拿到 socketio 实例
	const socketioRef = useRef<Socket>()
	// 创建聊天列表的 ref 对象
	const chatListRef = useRef<HTMLDivElement>(null)

	// 在 useEffect 中，创建 websocket 实例，并验证连接成功
	useEffect(() => {
		//1、简历连接
		const socketio = io('http://toutiao.itheima.net', {
			query: {
				token,
			},
			//连接方式
			transports: ['websocket'],
		})

		// 2、连接成功  socketio 连接成功时，就会执行此处的回调函数
		socketio.on('connect', () => {
			console.log('socketio 链接成功')
			// 让小智给你打个招呼
			setChatList([
				{
					type: 'xz',
					message: '你好，我是小智',
				},
				{
					type: 'xz',
					message: '你有什么疑问？',
				},
			])
		})

		// 接收 websocket 服务器返回的消息
		socketio.on('message', (data) => {
			setChatList((chatList) => [
				...chatList,
				{
					type: 'xz',
					message: data.msg,
				},
			])
		})

		// 将 socketio 对象存储到 ref 中
		socketioRef.current = socketio

		return () => {
			// 在组件卸载时，关闭 socket 链接
			socketio.close()
		}
	}, [token])

  // 能够在聊天时展示最新的聊天内容
	// 监听聊天内容的改变，只要聊天内容改变了，就滚动列表列表到最底部
	useEffect(() => {
		const chatListDOM = chatListRef.current
		if (!chatListDOM) return

		chatListDOM.scrollTop = chatListDOM.scrollHeight
	}, [chatList])

	// 发送消息
	const onSendMessage = (e: React.KeyboardEvent<HTMLInputElement>) => {
		// https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/code
		if (e.code === 'Enter') {
      // 在敲回车时，发送消息
			setChatList([
				...chatList,
				{
					type: 'user',
					message: value,
				},
			])
			setValue('')

			// 将消息发送给 websocket 服务器
			socketioRef.current?.emit('message', {
				msg: value,
				timestamp: Date.now() + '',
			})
		}
	}

	return (
		<div className={styles.root}>
			<NavBar className='fixed-header' onBack={() => history.go(-1)}>
				小智同学
			</NavBar>

			<div className='chat-list' ref={chatListRef}>
				{chatList.map((item, index) => (
					<div
						key={index}
						className={classnames(
							'chat-item',
							item.type === 'xz' ? 'self' : 'user'
						)}
					>
						{item.type === 'xz' ? (
							<Icon type='iconbtn_xiaozhitongxue' />
						) : (
							<img
								src='http://geek.itheima.net/images/user_head.jpg'
								alt=''
							/>
						)}
						<div className='message'>{item.message}</div>
					</div>
				))}
			</div>

			<div className='input-footer'>
				<Input
					className='no-border'
					placeholder='请描述您的问题'
					value={value}
					onChange={(val) => setValue(val)}
					onKeyDown={onSendMessage}
				/>
				<Icon type='iconbianji' />
			</div>
		</div>
	)
}

export default Chat
